package com.robusta.cityuate.activities;

import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.VisibleRegion;
import com.robusta.cityuate.R;
import com.robusta.cityuate.base.CityuateFragmentMenuActivity;
import com.robusta.cityuate.fragments.SpotsMapFragment;
import com.robusta.cityuate.objects.Spot;
import com.robusta.cityuate.services.CityuateBroadCastReceiver;
import com.robusta.cityuate.services.HTTPService;
import com.robusta.cityuate.services.SpotsListService;
import com.robusta.cityuate.utils.ConnectionUtils;
import com.robusta.cityuate.utils.LocationUtils;
import com.slidingmenu.lib.SlidingMenu;
import com.slidingmenu.lib.SlidingMenu.OnClosedListener;
import com.slidingmenu.lib.SlidingMenu.OnOpenListener;

public class FindSpotsMapActivity extends CityuateFragmentMenuActivity
		implements OnCameraChangeListener {

	private static final String GET_TAG = FindSpotsMapActivity.class.getName()
			+ "_GETLIST";
	private static final double FACTOR = 3;
	private GoogleMap mMap;
	private UiSettings mapUISettings;
	private LocationManager locationManager;
	private HashMap<Marker, Spot> markerSpotsMap = new HashMap<Marker, Spot>();
	private LatLng farpoint;
	private LatLng center;
	private double range;

	private CityuateBroadCastReceiver getListReceiver = new CityuateBroadCastReceiver() {
		@Override
		public void onSuccess() {
			fillSpotsList();
		}

		@Override
		public void onFailure() {
			spotsListFuilure();
		}

		@Override
		public void onCancel() {

		}
	};
	private Context mContext = this;
	private SpotsMapFragment mapFragment;

	@Override
	public void onCreate(Bundle arg0) {
		super.onCreate(arg0);
		setContentView(R.layout.find_spots_map_view);
		mapFragment = (SpotsMapFragment) getSupportFragmentManager()
				.findFragmentById(R.id.map);

		setUpMapIfNeeded();
		sideMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE);
		sideMenu.setOnClosedListener(new OnClosedListener() {

			@Override
			public void onClosed() {
				mapFragment.getView().setVisibility(View.VISIBLE);

			}
		});
		sideMenu.setOnOpenListener(new OnOpenListener() {

			@Override
			public void onOpen() {
				mapFragment.getView().setVisibility(View.GONE);

			}

		});
	}

	@Override
	protected void onResume() {
		super.onResume();
		// setUpMapIfNeeded();
		registerReceiver(getListReceiver, new IntentFilter(GET_TAG));

		if (ConnectionUtils.isConnecting(mContext, GET_TAG)) {
			setSupportProgressBarIndeterminateVisibility(true);
		} else {
			if (ConnectionUtils.wasConnected(mContext, GET_TAG))
				if (ConnectionUtils.isResultSuccessful(mContext, GET_TAG)) {
					Log.d(GET_TAG, "OnResume result ok");
					fillSpotsList();
				} else {
					Log.d(GET_TAG, "OnResume result fail");
					spotsListFuilure();
				}
			else {
				Log.d(GET_TAG, "OnResume get spots");

			}
		}

	}

	@Override
	protected void onPause() {
		super.onPause();
		unregisterReceiver(getListReceiver);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// if (!ConnectionUtils.isConnecting(mContext, GET_TAG))
		ConnectionUtils.clearConnection(mContext, GET_TAG);

	}

	private void setUpMapIfNeeded() {
		// Do a null check to confirm that we have not already instantiated the
		// map.
		if (mMap == null) {
			// Try to obtain the map from the SupportMapFragment.
			mMap = ((SupportMapFragment) getSupportFragmentManager()
					.findFragmentById(R.id.map)).getMap();
			mMap.setOnCameraChangeListener(this);

		}
		if (mMap != null)
			setUpMap();

	}

	/**
	 * configure map options
	 */
	private void setUpMap() {
		mMap.setMyLocationEnabled(true);
		mapUISettings = mMap.getUiSettings();
		mapUISettings.setCompassEnabled(true);
		mapUISettings.setMyLocationButtonEnabled(true);
		LatLng currentLocation;
		if (mMap.getMyLocation() != null) {
			currentLocation = new LatLng(mMap.getMyLocation().getLatitude(),
					mMap.getMyLocation().getLongitude());
			mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
					currentLocation, 14));
		} else {
			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			Location c = locationManager
					.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
			if (c != null) {
				currentLocation = new LatLng(c.getLatitude(), c.getLongitude());
				mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
						currentLocation, 14));
			}
		}
	}

	/**
	 * list of spots received
	 */
	public void fillSpotsList() {
		setSupportProgressBarIndeterminateVisibility(false);

		String josnList = ConnectionUtils.getExtra(mContext, GET_TAG);
		if (josnList == null) {
			Log.e(GET_TAG, "emptylist");
			return;
		}
		try {
			mMap.clear();
			markerSpotsMap.clear();
			JSONArray spotslist = new JSONArray(josnList);
			Log.e(GET_TAG, "received " + spotslist.length());

			for (int i = 0; i < spotslist.length(); i++) {
				Spot spot = Spot.createFromJSON(spotslist.getJSONObject(i));
				mapFragment.addMarker(spot);
			}

		} catch (JSONException e) {
			e.printStackTrace();
		}

	}

	/**
	 * fail to get spots
	 */
	public void spotsListFuilure() {
		setSupportProgressBarIndeterminateVisibility(false);

		Toast.makeText(mContext, ConnectionUtils.getExtra(mContext, GET_TAG),
				Toast.LENGTH_LONG).show();
		ConnectionUtils.clearConnection(mContext, GET_TAG);
	}

	/**
	 * firing service to get spots list
	 */
	public void getSpotsList() {

		if (!ConnectionUtils.isNetworkAvailable(mContext)) // {
			// No connection
			ConnectionUtils.showNoConnectionDialog(mContext);
		setSupportProgressBarIndeterminateVisibility(true);

		startSpotsListService();

	}

	public void startSpotsListService() {

		updateParamters();
		// System.out.println(range);
		// System.out.println(center.latitude+" "+center.longitude+" far "+farpoint.latitude+" "+farpoint.longitude);

		Intent backgroud_regService = new Intent(mContext,
				SpotsListService.class);
		backgroud_regService.setAction(GET_TAG);
		backgroud_regService.putExtra(HTTPService.LOGIN_RQUIRED, true);
		backgroud_regService.putExtra(SpotsListService.LATIT, center.latitude);
		backgroud_regService
				.putExtra(SpotsListService.LONGIT, center.longitude);
		backgroud_regService.putExtra(SpotsListService.RADUIS, range);

		backgroud_regService.putExtra(SpotsListService.LIST_TYPE, 3);
		mContext.startService(backgroud_regService);
		Log.e("Fragment", "Fired spots service");
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getSupportMenuInflater();
		inflater.inflate(R.menu.find_spots_map_option_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.refresh: {
			getSpotsList();
			return true;
		}

		case android.R.id.home: {
			toggle();
			return true;
		}
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onCameraChange(CameraPosition position) {
		VisibleRegion visibleRegion = mMap.getProjection().getVisibleRegion();
		farpoint = visibleRegion.farLeft;
		if (center == null
				|| LocationUtils.getDistanceFromLatLonInKm(center,
						position.target) > range
				|| LocationUtils.getDistanceFromLatLonInKm(center, farpoint) > range) {
			getSpotsList();
		}
	}

	private void updateParamters() {
		VisibleRegion visibleRegion = mMap.getProjection().getVisibleRegion();
		farpoint = visibleRegion.farLeft;
		center = mMap.getCameraPosition().target;
		range = LocationUtils.getDistanceFromLatLonInKm(center, farpoint)
				* FACTOR;
	}

}
